package com.stox.client.ui.javafx.chartingy.model.shape;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Point2D;
import javafx.scene.shape.Line;

import com.stox.client.ui.javafx.chartingy.model.chart.Chart;

public class TrendLine extends Shape {

	private final ControlPoint start;
	private final ControlPoint end;
	private final ControlPoint movePoint;
	private final Line line = new Line();
	private boolean moving = false;
	private final ChangeListener<Number> listener = new ChangeListener<Number>() {
		@Override
		public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
			if (!moving) {
				moving = true;
				movePoint.setCenterY((start.getCenterY() + end.getCenterY()) / 2);
				movePoint.setCenterX((start.getCenterX() + end.getCenterX()) / 2);
				moving = false;
			}
			Point2D point = extrapolate(start, end, getChart().getChartContentArea().getLayoutBounds());
			line.setEndX(point.getX());
			line.setEndY(point.getY());
			point = extrapolate(end, start, getChart().getChartContentArea().getLayoutBounds());
			line.setStartX(point.getX());
			line.setStartY(point.getY());
		}
	};


	public TrendLine(final Chart<?, ?> chart, final double initialSceneX, final double initialSceneY) {
		super(chart);
		start = new ControlPoint(chart);
		end = new ControlPoint(chart);
		movePoint = new ControlPoint(chart);

		deletePoint.centerXProperty().bind(start.centerXProperty().add(end.centerXProperty().subtract(start.centerXProperty()).multiply(3).divide(4)));
		deletePoint.centerYProperty().bind(start.centerYProperty().add(end.centerYProperty().subtract(start.centerYProperty()).multiply(3).divide(4)));

		start.centerXProperty().addListener(listener);
		end.centerXProperty().addListener(listener);
		start.centerYProperty().addListener(listener);
		end.centerYProperty().addListener(listener);

		movePoint.centerXProperty().addListener(new ChangeListener<Number>() {
			@Override
			public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
				if ((0 < oldValue.doubleValue()) && !moving) {
					moving = true;
					double delta = oldValue.doubleValue() - start.getCenterX();
					start.setCenterX(newValue.doubleValue() - delta);
					delta = end.getCenterX() - oldValue.doubleValue();
					end.setCenterX(newValue.doubleValue() + delta);
					moving = false;
				}
			}
		});


		movePoint.centerYProperty().addListener(new ChangeListener<Number>() {
			@Override
			public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
				if ((0 < oldValue.doubleValue()) && !moving) {
					moving = true;
					double delta = oldValue.doubleValue() - start.getCenterY();
					start.setCenterY(newValue.doubleValue() - delta);
					delta = end.getCenterY() - oldValue.doubleValue();
					end.setCenterY(newValue.doubleValue() + delta);
					moving = false;
				}
			}
		});

		final Point2D point = chart.getChartContentArea().sceneToLocal(initialSceneX, initialSceneY);
		start.setCenterY(point.getY());
		start.setCenterX(point.getX());
		end.setCenterY(point.getY());
		end.setCenterX(point.getX());
		movePoint.setCenterX(point.getX());
		movePoint.setCenterY(point.getY());
		getChildren().addAll(start, line, movePoint, deletePoint, end);
	}

	public ControlPoint getEnd() {
		return end;
	}

	@Override
	public void update() {
		start.update();
		end.update();
	}

}
